package it.polimi.jita.cp.block.de;

import it.polimi.jita.cp.block.InputBuilder;
import it.polimi.jita.cp.block.de.DemandEstimatorInput.Instant;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

public class DemandEstimatorInputBuilder extends
		InputBuilder<DemandEstimatorInput> {

	private Map<WorldState, Integer> worldStateIndex = new HashMap<>();

	public DemandEstimatorInputBuilder() {
		super();
		WorldState[] worldStates = WorldState.values();
		for (WorldState worldState : worldStates) {
			worldStateIndex.put(worldState, worldState.ordinal());
		}

	}

	@Override
	protected DemandEstimatorInput createInput() throws IOException {

		String filePath = getOptionValue("-i");
		Integer samplingInt = Integer.parseInt(getOptionValue("-s"));
		Integer vCpuNum = Integer.parseInt(getOptionValue("-vcpu"));

		// TODO Log open file
		System.out.println(String.format("Opening file: %s", filePath));

		List<IInstantDemandEstimatorData> capacityLog = new ArrayList<>();

		URL url = this.getClass().getClassLoader().getResource(filePath);
		InputStream in = url.openStream();
		InputStreamReader isr = new InputStreamReader(in);
		CSVParser csvParser = new CSVParser(isr, CSVFormat.DEFAULT);
		System.out.println(String.format("Reading file: %s", filePath));

		boolean needToCheckHeader = false;
		if (getCl().hasOption("-h")) {
			needToCheckHeader = true;
		}

		for (Iterator<CSVRecord> iterator = csvParser.iterator(); iterator
				.hasNext();) {
			CSVRecord csvRecord = iterator.next();
			if (needToCheckHeader) {
				for (int i = 0; i < csvRecord.size(); i++) {
					try {
						WorldState ws = WorldState.valueOf(csvRecord.get(i)
								.toUpperCase());
						worldStateIndex.put(ws, i);
					} catch (Exception e) {
						System.out.println(String.format(
								"Word '%s' is not recognized as WorldState",
								csvRecord.get(i)));
					}
				}

				needToCheckHeader = false;

			} else {
				Double runDbl = Double.parseDouble(csvRecord
						.get(worldStateIndex.get(WorldState.RUN)));
				Double blockDbl = Double.parseDouble(csvRecord
						.get(worldStateIndex.get(WorldState.BLOCK)));
				Double waitDbl = Double.parseDouble(csvRecord
						.get(worldStateIndex.get(WorldState.WAIT)));

				Double block = new Double(blockDbl / samplingInt / vCpuNum);
				Double wait = new Double(waitDbl / samplingInt / vCpuNum);
				Double run = new Double(runDbl / samplingInt / vCpuNum);
				Instant instant = new Instant(block, wait, run);
				capacityLog.add(instant);
			}
		}
		csvParser.close();

		DemandEstimatorInput input = new DemandEstimatorInput(capacityLog,
				samplingInt, getOptionValue("-o"), getCl().hasOption("-h"),
				vCpuNum);
		return input;
	}

	public static enum WorldState {
		RUN, WAIT, BLOCK
	}

}
